﻿using UnityEngine;
using System.Collections;
using System;

namespace BF
{
    public class AudioSourceCell : MonoRecycleItem
    {
        public AudioSource audioSource;

        public int id
        {
            get
            {
                _id = _id ?? GetInstanceID();
                return _id.Value;
            }
        }
        public bool isBGM { get; private set; }
        public float interval { get; private set; }
        public AudioPlayType audioPlayType { get; private set; }
        public string clipName { get; private set; }

        private int? _id;
        private int _loop = 1;
        private float _duration;
        private float _delay;
        private AudioClip _clip;

        private bool _isPlay;

        private Func<AudioSourceCell, bool> _canPlay;
        private Action<AudioSourceCell> _onRecordPlay;
        private Action<AudioSourceCell> _onRecyle;

        /// <summary>
        /// 设置播放循环次数,loop < 1则为循环
        /// </summary>
        public AudioSourceCell SetLoop(int loop)
        {
            this._loop = loop;
            if (loop < 1)
            {
                audioSource.loop = true;
            }
            else
            {
                audioSource.loop = false;
            }
            return this;
        }

        /// <summary>
        /// 设置播放时长，如果时长>Clip时长则会自动循环,设置这个值则会不管loop次数
        /// </summary>
        public AudioSourceCell SetDuration(float duration)
        {
            this._duration = duration;
            return this;
        }

        /// <summary>
        /// 设置播放延迟时间
        /// </summary>
        public AudioSourceCell SetDelay(float delay)
        {
            this._delay = delay;
            audioSource.playOnAwake = delay <= 0;
            return this;
        }

        /// <summary>
        /// 设置最小播放间隔，小于该值则不会播放
        /// </summary>
        public AudioSourceCell SetInterval(float interval)
        {
            this.interval = interval;
            return this;
        }

        /// <summary>
        /// 设置播放音量大小
        /// </summary>
        public AudioSourceCell SetVol(float vol)
        {
            audioSource.volume = vol;
            return this;
        }

        /// <summary>
        /// 设置播放类型
        /// </summary>
        public AudioSourceCell SetAudioPlayType(AudioPlayType audioPlayType)
        {
            this.audioPlayType = audioPlayType;
            return this;
        }

        /// <summary>
        /// 设置音效片段
        /// </summary>
        public AudioSourceCell SetClip(AudioClip clip)
        {
            audioSource.clip = clip;
            this._clip = clip;
            return this;
        }

        /// <summary>
        /// 设置音效名
        /// </summary>
        public void SetClipName(string clipName)
        {
            this.isBGM = clipName.Contains("BGM") || clipName.Contains("bgm");
            this.clipName = clipName;
        }

        public void SendAction(Func<AudioSourceCell, bool> canPlay, Action<AudioSourceCell> onRecordPlay, Action<AudioSourceCell> onRecyle)
        {
            this._canPlay = canPlay;
            this._onRecordPlay = onRecordPlay;
            this._onRecyle = onRecyle;
        }

        /// <summary>
        /// 播放音乐音效
        /// </summary>
        public void Play()
        {
            DoPlay();
        }

        private void DoPlay()
        {
            if (!_canPlay(this))
            {
                this.ReturnToPool();
                return;
            }

            _onRecordPlay(this);
            _isPlay = true;

            //#if DEBUG
            //        Debug.Log($"[AudioSourceCell][{_G.time}] play audio: {clipName}");
            //#endif

            if (audioSource.loop)
            {
                audioSource.Play();
            }
            else
            {
                float audioLength = _clip.length;
                int loop = this._duration <= 0 ? _loop : Mathf.CeilToInt(this._duration / audioLength);
                audioSource.loop = loop > 1;
                if (_delay > 0)
                {
                    audioSource.PlayDelayed(_delay);
                }
                else
                {
                    audioSource.Play();
                }

                if (loop != int.MaxValue)
                {
                    float timeToStop = this._duration <= 0 ? _delay + (loop + 1) * audioLength : _delay + _duration;

                    Timer.Pop().Delay(timeToStop).Action(Stop).Execute();
                }
            }

            RefreshAudioOnOff();
        }


        /// <summary>
        /// 刷新音乐音效开关状态
        /// </summary>
        public void RefreshAudioOnOff()
        {
            if (this == null)
            {
                return;
            }
            if (this.audioSource == null)
            {
                this.Destroy();
                return;
            }

            if (this.isBGM)
            {
                if (this.audioSource.mute != AudioManager.isMuteMusic)
                {
                    this.audioSource.mute = AudioManager.isMuteMusic;
                }
            }
            else
            {
                if (this.audioSource.mute != AudioManager.isMuteAudio)
                {
                    this.audioSource.mute = AudioManager.isMuteAudio;
                }
            }
        }

        public void Pause()
        {
            audioSource.Pause();
        }

        public void Resume()
        {
            audioSource.UnPause();
        }

        public void Stop()
        {
            ReturnToPool();
        }

        /// <summary>
        /// 回收
        /// </summary>
        public override void OnRecycle()
        {
            if (_isPlay)
            {
                _onRecyle?.Invoke(this);
            }

            _isPlay = false;
            _loop = 1;
            _duration = 0;
            _delay = 0;
            interval = 0;
            isBGM = false;

            audioSource.Stop();

            audioSource.playOnAwake = true;
            audioSource.loop = false;
            audioSource.volume = 1;
            audioSource.clip = null;

            audioPlayType = AudioPlayType.Normal;

            this.gameObject.SetActive(false);

            base.OnRecycle();
        }
    }
}